`include "PRV564Config.v"
`include "PRV564Define.v"
module CSR_top
#(
    parameter HARTID = 'h0
)
(
    input wire              CLKi, ARSTi,
    //-------------signals and value from platform--------------
    input wire [`XLEN-1:0]  mtime,                                          //Machine mode time in
    input wire              Interrupt_MEI, Interrupt_MSI, Interrupt_MTI,    //Interrupt from platfrom controller
    input wire              Interrupt_SEI,
    //---------------pipiline flush and new PC-------------------
    output reg              Global_Flush,
    output reg [`XLEN-1:0]  Global_newPC,
    //--------------------read csr port-------------------------
    input wire              csr_rden,
    input wire [11:0]       csr_rdindex,
    output reg [`XLEN-1:0]  csr_rddata,
    output wire [43:0]      csr_satpppn,
    output wire [3:0]       csr_satpmode,
    output wire             csr_tsr, csr_tvm, csr_sum, csr_mpriv, csr_mxr, csr_mige, csr_sige,
    output wire [`XLEN-1:0] csr_mideleg, csr_medeleg, csr_mip, csr_mie,
    output wire [1:0]       csr_priv, csr_mpp,
    output wire             csr_InhibitIcache, csr_InhibitDcache, csr_DCacheWT,
    //---------------commit information-----------------------
    input wire              CMT_valid,
    input wire              CMT_csren,
    input wire [11:0]       CMT_csrindex,
    input wire [`XLEN-1:0]  CMT_pc,
    input wire [`XLEN-1:0]  CMT_data2,
    input wire              CMT_mret,
    input wire              CMT_sret,
    input wire              CMT_system,
    input wire [`XLEN-1:0]  CMT_trap_cause,
    input wire [`XLEN-1:0]  CMT_trap_pc,
    input wire [`XLEN-1:0]  CMT_trap_value,
    input wire              CMT_trap_m,
    input wire              CMT_trap_s,
    input wire              CMT_trap_async
`ifdef DEBUG_FLAG
    ,output [ 1:0] privilege,
    output [63:0] mstatus,
    output [63:0] sstatus,
    output [63:0] mepc,
    output [63:0] sepc,
    output [63:0] mtval,
    output [63:0] stval,
    output [63:0] mtvec,
    output [63:0] stvec,
    output [63:0] mcause,
    output [63:0] scause,
    output [63:0] satp,
    output [63:0] mip,
    output [63:0] mie,
    output [63:0] mscratch,
    output [63:0] sscratch,
    output [63:0] mideleg,
    output [63:0] medeleg,
    //TRAP EVENT
    output       trap_valid,
    output[ 2:0] trap_code,
    output[63:0] trap_pc,
    output[63:0] mcycle,
    output[63:0] minstret,
    //ARCH EVENT
    output [31:0] intrNO,
    output [31:0] cause,
    output [63:0] exceptionPC
`endif
);
/***********************************************************************************
                                注意事项
    当指令是一条system指令时，这条指令是不会有异步异常的！ 否则就出现了中断咬人！
    执行完成system类指令后，会引起流水线全局冲刷

************************************************************************************/
//---------------------Machine and Supervisior trap setup--------------------
`ifndef DEBUG_FLAG
    wire [`XLEN-1:0] mstatus,  mie;            //M模式Trap管理寄存器
    wire [`XLEN-1:0] sstatus, satp ;           //S模式Trap管理寄存器
    wire [`XLEN-1:0] mtvec,     stvec,  mideleg,    medeleg;
    wire [1:0]       privilege;
//--------------------Machine and Supervisior trap handle---------------------
    wire [`XLEN-1:0] mip;                                  //Machine and Supervisior mode interrupt pending
    wire [`XLEN-1:0] mscratch, mepc, mcause, mtval;             //
    wire [`XLEN-1:0] sscratch, sepc, scause, stval;
`endif
//------------------Supervisior Virtual Translation---------------------------
    wire [`XLEN-1:0]  sip, sie,  scounteren,  misa,          mcounteren;            //S模式Trap管理寄存器
    reg  [43:0]      satp_ppn;
    reg  [3:0]       satp_mode;

always@(posedge CLKi or posedge ARSTi)begin
    if(ARSTi)begin
        satp_ppn <= 'h0;
        satp_mode<= `Sv39_Bare;
    end
    else if(CMT_csren)begin
        if(CMT_csrindex == `srw_satp_index)begin
            satp_ppn <= CMT_data2[43:0];
            satp_mode<= CMT_data2[63:60];
        end
    end
end
assign satp = {satp_mode,16'b0,satp_ppn};
assign csr_satpppn = satp_ppn;
assign csr_satpmode= satp_mode;
//------------------Information register------------------------------------
    wire [`XLEN-1:0] mhartid, mvendorid, marchid, mimpid;
    reg  [`XLEN-1:0] mtime_copy;                                 //a copy of mtime
always@(posedge CLKi)begin
    mtime_copy <= mtime;
end
//----------------======---cycle and counter-----------------------------------
`ifndef DEBUG_FLAG
    wire [`XLEN-1:0] mcycle, minstret;
`endif
    wire [`XLEN-1:0] mcountinhibit;

//------------------------read CSR port ------------------------------------------
always@(*)begin
    if(csr_rden)begin
        case(csr_rdindex)
		`uro_cycle_index		:	csr_rddata = mcycle;
		`uro_time_index			:	csr_rddata = mtime_copy;
		`uro_instret_index		:	csr_rddata = minstret;
		`srw_sstatus_index		:	csr_rddata = sstatus;
		`srw_sie_index			:	csr_rddata = sie;
		`srw_stvec_index		:	csr_rddata = stvec;
		`srw_scounteren_index	:	csr_rddata = scounteren;
		`srw_sscratch_index		:	csr_rddata = sscratch;
		`srw_sepc_index			:	csr_rddata = sepc;
		`srw_scause_index		:	csr_rddata = scause;
		`srw_stval_index		:	csr_rddata = stval;
		`srw_sip_index			:	csr_rddata = sip;
		`srw_satp_index			:	csr_rddata = satp;
		`mro_mvendorid_index	:	csr_rddata = mvendorid;
		`mro_marchid_index		:	csr_rddata = marchid;
		`mro_mimp_index			:	csr_rddata = mimpid;
		`mro_mhardid_index		:	csr_rddata = mhartid;
		`mro_misa_index			:	csr_rddata = misa;
		`mrw_mstatus_index		:	csr_rddata = mstatus;
		`mrw_medeleg_index		:	csr_rddata = medeleg;
		`mrw_mideleg_index		:	csr_rddata = mideleg;
		`mrw_mie_index			:	csr_rddata = mie;
		`mrw_mtvec_index		:	csr_rddata = mtvec;
		`mrw_mcounteren_index	:	csr_rddata = mcounteren;
		`mrw_mscratch_index		:	csr_rddata = mscratch;
		`mrw_mepc_index			:	csr_rddata = mepc;
		`mrw_mcause_index		:	csr_rddata = mcause;
		`mrw_mtval_index		:	csr_rddata = mtval;
		`mrw_mip_index			:	csr_rddata = mip;
		`mrw_mcycle_index		:	csr_rddata = mcycle;
		`mrw_minstret_index		:	csr_rddata = minstret;
		`mrw_mcountinhibit_index: csr_rddata = mcountinhibit;
			default				:	csr_rddata = 64'h0;
	    endcase
    end
    else begin
        csr_rddata = 'h0;          //no read, no result
    end
end
assign csr_tsr  = mstatus[22];
assign csr_tvm  = mstatus[20];
assign csr_mxr  = mstatus[19];
assign csr_sum  = mstatus[18];
assign csr_mpriv=mstatus[17];
assign csr_mpp  = mstatus[12:11];
assign csr_mige =mstatus[3];
assign csr_sige =mstatus[1];
assign csr_priv = privilege;
assign csr_mideleg=mideleg;
assign csr_medeleg=medeleg;
assign csr_mip  = mip;
assign csr_mie  = mie;
//-------------------Generate Global Flush and new PC------------------------
always@(*)begin
    if(CMT_mret)begin
        Global_Flush = 1'b1;
        Global_newPC = mepc;
    end
    else if(CMT_sret)begin
        Global_Flush = 1'b1;
        Global_newPC = sepc;
    end
    else if(CMT_trap_m)begin            //当前异常交给M模式处理
        if(CMT_trap_async)begin
            Global_Flush = 1'b1;
            Global_newPC = (mtvec[1:0]==2'h1) ? ({mtvec[63:2],2'b0} + {CMT_trap_cause[61:0],2'b00}) : {mtvec[63:2],2'b0};
        end
        else begin
            Global_Flush = 1'b1;
            Global_newPC = {mtvec[63:2],2'b0};
        end
    end
    else if(CMT_trap_s)begin            //当前异常交给S模式处理
        if(CMT_trap_async)begin         //发生不同步异常，即中断时
            Global_Flush = 1'b1;
            Global_newPC = (stvec[1:0]==2'h1) ? ({stvec[63:2],2'b0} + {CMT_trap_cause[61:0],2'b00}) : {stvec[63:2],2'b0};
        end
        else begin
            Global_Flush = 1'b1;   
            Global_newPC = {stvec[63:2],2'b0};
        end
    end
    else if(CMT_system)begin         //如果此条指令是一条system类型的指令，则执行完成后对流水线进行刷新
        Global_Flush = 1'b1;
        Global_newPC = CMT_pc + 'd4;
    end
    else begin
        Global_Flush = 1'b0;
        Global_newPC = 'hx;
    end
end
//------------------------Trap setup--------------------------
TrapSetup           TrapSetup(
    .CLKi               (CLKi), 
    .ARSTi              (ARSTi),
    //-----------CSR value output----------
    .mstatus            (mstatus), 
    .misa               (misa), 
    .mie                (mie), 
    .mcounteren         (mcounteren),
    .sstatus            (sstatus),       
    .sie                (sie), 
    .scounteren         (scounteren),
    .mtvec              (mtvec), 
    .stvec              (stvec), 
    .mideleg            (mideleg), 
    .medeleg            (medeleg),
    .privilege          (privilege),
    //-----------write back to csr---------
    .csr_index          (CMT_csrindex),
    .csr_data           (CMT_data2),
    .csr_wren           (CMT_csren),
    //------------return--------------------
    .mret               (CMT_mret), 
    .sret               (CMT_sret),
    //-----------trap-----------------------
    .trap_s             (CMT_trap_s), 
    .trap_m             (CMT_trap_m)
);

//--------------------Trap handle----------------------
TrapHandle          TrapHandle(
    .CLKi               (CLKi), 
    .ARSTi              (ARSTi),        //clock and global reset
    //---------------interrupt from platform controller-----
    .Interrupt_MEI      (Interrupt_MEI), 
    .Interrupt_MSI      (Interrupt_MSI), 
    .Interrupt_MTI      (Interrupt_MTI),
    .Interrupt_SEI      (Interrupt_SEI),
    //---------------csr value output-----------------
    .mip                (mip), 
    .sip                (sip),
    .mscratch           (mscratch), 
    .mepc               (mepc), 
    .mcause             (mcause), 
    .mtval              (mtval),
    .sscratch           (sscratch), 
    .sepc               (sepc), 
    .scause             (scause), 
    .stval              (stval),
    //-----------write back to csr---------
    .csr_index          (CMT_csrindex),
    .csr_data           (CMT_data2),
    .csr_wren           (CMT_csren),
    //-----------Trap value input----------
    .trap_value         (CMT_trap_value), 
    .trap_cause         (CMT_trap_cause), 
    .trap_pc            (CMT_trap_pc),
    .trap_s             (CMT_trap_s), 
    .trap_m             (CMT_trap_m), 
    .trap_async         (CMT_trap_async)
);

//---------------------Counters-----------------------
Counter             Counter(
    .CLKi               (CLKi), 
    .ARSTi              (ARSTi),
    .wb_valid           (CMT_valid),
    //-----------write back to csr---------
    .csr_index          (CMT_csrindex),
    .csr_data           (CMT_data2),
    .csr_wren           (CMT_csren),
    //---------
    .mcycle             (mcycle), 
    .minstret           (minstret),
    .mcountinhibit      (mcountinhibit)
);
//------------------Informations------------------------
InformCSR
#(
    .HARTID             (HARTID)
)InformCSR(
    .CLKi               (CLKi), 
    .ARSTi              (ARSTi),        //clock and global reset
    .mhartid            (mhartid), 
    .mvendorid          (mvendorid), 
    .marchid            (marchid), 
    .mimpid             (mimpid),
    .CSR_InhibitIcache  (csr_InhibitIcache),
    .CSR_InhibitDcache  (csr_InhibitDcache),
    .CSR_DCacheWT       (csr_DCacheWT),
    //----------write back---------------
    .csr_index          (CMT_csrindex),
    .csr_data           (CMT_data2),
    .csr_wren           (CMT_csren)
);
`ifdef DEBUG_FLAG

`endif
endmodule
